<?php
/**
 * Created by PhpStorm.
 * User: qgz
 * Date: 2017/8/26
 * Time: 14:19
 */

namespace Bpm\Controllers;

use Admin\Models\bpm\XHBpmNode;
use Admin\Models\bpm\XHBpmTemplate;
use Admin\Models\bpm\XHBpmOperatePro;
use Admin\Models\bpm\XHBpmOperateProNode;
use Admin\Models\bpm\XHBpmOperateProStand;
use Admin\Models\school\XhschoolInfo;
use Admin\Models\user\XhsysUser;
use Helpers\Assets;
use Helpers\Main;
use Helpers\Template;
use Helpers\Tool;
use Helpers\User;
use Modules\Power;
use Modules\School;
use Services\BigData;

class OperateProController extends ControllerBase
{
    public static $status = [
        '1' => '<div style="background-color:red;color: white;">未完成</div>',
        '2' => '<div style="background-color:green;color: white;">完成</div>'
    ];

    /**
     * 运营项目
     *
     * @return \Phalcon\Mvc\View|string
     *
     * create by qgz 20180826
     */
    public function operateProListAction()
    {
        if (!Power::exist('Bpm_OperatePro')) {
            return $this->sendViewError('您没有权限访问');
        }
        Assets::easyUI();
        $this->view->pick('operatePro/operatePro');
        Assets::importJs('js/operatePro/operatePro.js');
        $this->di->get('assets')->addCss('bpm/css/Color.css');
        $listSearchArr = $listButtonArr = [];
        if (Power::exist('Bpm_OperatePro_Add')) {
            $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_add', 'text' => '新增', 'icon' => 'fa-plus'];
        }
        if (Power::exist('Bpm_OperatePro_Edit')) {
            $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_check', 'text' => '确认完成', 'icon' => 'fa-check'];
            $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_unCheck', 'text' => '取消完成', 'icon' => 'fa-history'];
        }
        if (Power::exist('Bpm_OperatePro_Del')) {
            $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_del', 'text' => '删除', 'icon' => 'fa-trash'];
        }
        if (Power::exist('Bpm_OperatePro_Stat')) {
            $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_stat',
                                'text' => '应用数据统计', 'icon' => 'fa-bar-chart'];
            if (strpos($_SERVER['HTTP_HOST'], 'admin.yunzuoye.net') === false) {//正式环境先不看
                $listButtonArr[] = ['plain' => 'true', 'id' => 'bt_list_teaAppStat',
                                    'text' => '教师应用统计', 'icon' => 'fa-table'];
            }
        }
        $listSearchArr[] = ['type' => 'text', 'id' => 'list_vague', 'label' => ' 搜索： '];
        $listSearchArr[] = ['type' => 'button', 'id' => 'bt_list_search', 'text' => '查找', 'icon' => 'fa-search',
                            'style' => 'margin-left:10px'];
        return $this->view->setVars([
            'List' => Template::createList('list', 'operateProList', [
                'searchToolbar' => Template::createSearchToolBar($listSearchArr, !!$listButtonArr),
                'buttonToolbar' => Template::createButtonToolBar($listButtonArr)
            ])
        ]);
    }

    /**
     * 获取运营项目数据
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180826
     * modify by qgz 20180919 操作后刷新该节点展开
     */
    public function getOperateProDataAction()
    {
        try {
            $status = $this->request->get('search');
            $openId = $this->request->getPost('openId');
            if (!Power::exist('Bpm_OperatePro')) {
                return $this->sendErrorResponse(400, '您没有权限访问');
            }
            if (strpos($openId, '_') !== false) {
                $openId = explode('_', $openId);
            }
            $parameters = [
                'conditions' => ' bDelete = 0 ',
                'order' => 'tCreateDate DESC',
            ];
            if ($status['vague']) {//搜索学校
                $machId = School::searchSchool($status['vague']);
                if (!empty($machId)) {
                    $machId = implode(',', $machId);
                    $parameters['conditions'] .= " and iSchoolId in ($machId) ";
                }
            }
            $schoolIds = School::getPower();
            if (!$schoolIds) {
                return $this->sendJsonResponse(['total' => 0, 'rows' => []]);
            } elseif ($schoolIds !== true) {
                $parameters['conditions'] .= ' and iSchoolId IN (' . implode(',', $schoolIds) . ') ';
            }
            $enum['iStatus'] = self::$status;
            $data = Main::runModelPage('Admin\\Models\\bpm\\XHBpmOperatePro', $parameters, $enum);
            if ($data['total'] == 0) {
                return $this->sendJsonResponse($data);
            }
            Main::runUserNameById(
                $data['rows'],
                ['iCreateUserId' => 'iCreateUserId', 'iLastModifyUserId' => 'iLastModifyUserId'],
                true
            );
            Main::runSchoolNameByIdStr($data['rows'], ['iSchoolId' => 'nodeName']);
            $ids = array_column($data['rows'], 'iId');
            $tempIds = array_column($data['rows'], 'iTempId');
            $newNodes = $nodes = [];
            $nodeDataArr = XHBpmNode::find([
                'columns' => 'iNodeId, sNodeName',
                'conditions' => " iTPId in ({ids:array}) ",
                'bind'   => ['ids' => $tempIds ]
            ])->toArray();
            $nodeDataArr = array_column($nodeDataArr, 'sNodeName', 'iNodeId');//模板id-名称对
            if ($ids) {//获取节点数据
                $nodes = XHBpmOperateProNode::find([
                    'columns' => '*',
                    'conditions' => "bDelete= 0 and iOperateProId in ({ids:array}) ",
                    'bind'   => ['ids' => $ids ],
                    'order'  => 'iSort,iNodeId,iTempId,iOperateProId'
                ]);
                if ($nodes) {
                    $nodes = $nodes->toArray();
                    foreach ($nodes as $node) {
                        $newNodes[$node['iOperateProId']][] = $node;
                    }
                }
            }
            $tempEnumArr = $this->getTempEnum();
            foreach ($data['rows'] as &$row) {
                $row['sProgress'] = $this->addProgressColor($row['sProgress'], 1);
                $child = Tool::getValue($newNodes, $row['iId'], null);//如果有子节点加children
                if ($child) {
                    $row['state'] = 'closed';
                    $parentPath = [];
                    if ($openId) {
                        if (is_array($openId) && $row['iId'] == $openId[0]) {
                            $parentPath = $this->getPass($openId[1], $child, []);//父级节点路径,操作后刷新该节点展开
                            $row['state'] = 'open';
                        } elseif ($row['iId'] == $openId) {//最高层本身展开
                            $row['state'] = 'open';
                        }
                    }
                    $row['children'] = $this->runNode($child, $row, $nodeDataArr, $parentPath);
                }
                $row['depth'] = 0;
                $row['sFileUrl'] = $this->addFileStatus($row['sFileUrl'], $row['iId']);
                $row['iTempName'] = isset($tempEnumArr[$row['iTempId']]) ? $tempEnumArr[$row['iTempId']] : '';
            }
            unset($row);
            return $this->sendJsonResponse($data);
        } catch (\Exception $e) {
            return $this->sendErrorResponse(500, $e->getMessage());
        }
    }

    /**
     * 模板名枚举
     *
     * @return array
     *
     * create by qgz 20180918
     */
    public function getTempEnum()
    {
        $return = [];
        $data = XHBpmTemplate::find([
            'columns' => 'iTPId, sTPName',
            'conditions' => "bDelete = 0 and sTag = 'itemImpl'",
        ])->toArray();
        if ($data) {
            foreach ($data as $value) {
                $return[$value['iTPId']] = $value['sTPName'];
            }
        }
        return $return;
    }

    /**
     * 添加进度样式
     *
     * @param string $data
     * @param int $type
     *
     * @return string
     *
     * create by qgz 20180830
     */
    public function addProgressColor($data = '', $type = 1)
    {
        if (!$data) {
            return '0%';
        }
        $color = 'green';
        $frontColor = 'white';
        switch ($type) {
            case 1:
                $color = 'green';
                break;
            case 2:
                $color = '#428bca';
                break;
            case 3:
                $color = 'yellow';
                $frontColor = 'black';
                break;
        }
        $progress = ceil($data * 100);
        if ($progress < 20) {
            $frontColor = 'black';
        }
        $data = '<div title="' . $progress . '%" style="width: 100%;background-color: lightgrey">' .
                '<div style="background-color:' . $color . ';width: ' . $progress . '%;color: ' . $frontColor . ';' .
                'text-align: right" >' . $progress . '%</div></div>';
        return $data;
    }

    /**
     * 添加节点（第一层）
     *
     * @param array $child
     * @param array $parent
     * @param array $nodeDataArr
     * @param array $parentPathArr
     *
     * @return array
     *
     * create by qgz 20180826
     */
    public function runNode($child = [], $parent = [], $nodeDataArr = [], $parentPathArr = [])
    {
        $nodeArr = [];
        $classifyArr = [];
        foreach ($child as $item) {
            $classifyArr[$item['iParentId']][] = $item;
        }
        foreach ($classifyArr[0] as $item) { //第一层
            $depth = 1;
            $newArr = [
                'nodeName' => $nodeDataArr[$item['iNodeId']],
                'iId' => $parent['iId'] . '_' . $item['iNodeId'],
                'depth' => $depth,
                'sFileUrl' => $this->addFileStatus($item['sFileUrl'], $parent['iId'] . '_' . $item['iNodeId']),
                'iCreateUserId' => $item['iCreateUserId'],
                'iLastModifyUserId' => $item['iLastModifyUserId'],
            ];
            $newArr['iStatus'] = self::$status[$item['iStatus']];
            $newArr['tStartDate'] = $item['tStartDate'];
            $newArr['tEndDate'] = $item['tEndDate'];
            $newArr['tCompleteDate'] = $item['tCompleteDate'];
            $newArr['sRemark'] = $item['sRemark'];
            $newArr['sProgress'] = $this->addProgressColor($item['sProgress'], 2);
            $newChild = Tool::getValue($classifyArr, $item['iNodeId'], null); //获取是否存在子节点
            if ($newChild) {
                $newArr['children'] = $this->recursiveNode($classifyArr, $parent, $item['iNodeId'], $nodeDataArr, $depth, $parentPathArr); //子节点递归
                $newArr['state'] = 'closed';
                if (in_array($item['iNodeId'], $parentPathArr)) {//操作后刷新该节点展开
                    $newArr['state'] = 'open';
                }
            }
            $nodeArr[] = $newArr;
        }
        Main::runUserNameById(
            $nodeArr,
            ['iCreateUserId' => 'iCreateUserId', 'iLastModifyUserId' => 'iLastModifyUserId'],
            true
        );
        return $nodeArr;
    }

    /**
     * 遍历子节点
     *
     * @param $classifyArr
     * @param $parent
     * @param $currentNode
     * @param $nodeDataArr
     * @param $depth
     * @param $parentPathArr
     *
     * @return array
     *
     * create by qgz 20180903
     */
    public function recursiveNode($classifyArr, $parent, $currentNode, $nodeDataArr, $depth, $parentPathArr)
    {
        $nodeArr = [];
        $depth++;
        foreach ($classifyArr[$currentNode] as $item) {
            $newArr = [
                'nodeName' => $nodeDataArr[$item['iNodeId']],
                'iId' => $parent['iId'] . '_' . $item['iNodeId'],
                'depth' => $depth,
                'sFileUrl' => $this->addFileStatus($item['sFileUrl'], $parent['iId'] . '_' . $item['iNodeId']),
                'iCreateUserId' => $item['iCreateUserId'],
                'iLastModifyUserId' => $item['iLastModifyUserId'],
            ];
            $newArr['iStatus'] = self::$status[$item['iStatus']];
            $newArr['tStartDate'] = $item['tStartDate'];
            $newArr['tEndDate'] = $item['tEndDate'];
            $newArr['tCompleteDate'] = $item['tCompleteDate'];
            $newArr['sRemark'] = $item['sRemark'];
            $newArr['sProgress'] = $this->addProgressColor($item['sProgress'], 3);
            $newChild = Tool::getValue($classifyArr, $item['iNodeId'], null); //获取是否存在子节点
            if ($newChild) {
                $newArr['children'] = $this->recursiveNode($classifyArr, $parent, $item['iNodeId'], $nodeDataArr, $depth, $parentPathArr); //子节点递归
                $newArr['state'] = 'closed';
                if (in_array($item['iNodeId'], $parentPathArr)) {//操作后刷新该节点展开
                    $newArr['state'] = 'open';
                }
            }
            $nodeArr[] = $newArr;
        }
        Main::runUserNameById(
            $nodeArr,
            ['iCreateUserId' => 'iCreateUserId', 'iLastModifyUserId' => 'iLastModifyUserId'],
            true
        );
        return $nodeArr;
    }


    /**
     * 添加查看附件
     *
     * @param $data
     * @param $id
     *
     * @return string
     *
     * create by qgz 20180910
     */
    public function addFileStatus($data, $id)
    {
        $return = '';
        if (!$data) {
            return $return;
        }
        $return = '<div>' . '<a style="cursor:pointer" iId="' . $id . '" class="showFileTable"> 查看附件</a></div>';
        return $return;
    }

    /**
     * 附件展示页
     *
     * @return \Phalcon\Mvc\View|string
     *
     * create by qgz 20180910
     */
    public function showFileTableAction()
    {
        $id = $this->request->getQuery('id');
        if (!$id) {
            return $this->sendViewError('缺少参数');
        }
        if (strpos($id, '_') === false) {//最高层
            $pro = XHBpmOperatePro::findFirst([
                'conditions' => 'bDelete = 0 and iId = :iId:',
                'bind' => ['iId' => $id]
            ]);
            $idStr = $id;
        } else {
            $id = explode('_', $id);
            $pro = XHBpmOperateProNode::findFirst([
                'conditions' => 'bDelete = 0 and iNodeId = :iNodeId: and iOperateProId = :iOperateProId:',
                'bind' => ['iNodeId' => $id[1], 'iOperateProId' => $id[0]]
            ]);
            $idStr = $id[0] . '+' . $id[1];
        }
        if (!$pro) {
            return $this->sendViewError('暂无数据');
        }
        if (!$pro->sFileUrl) {
            $fileInfo = '0';
        } else {
            $fileInfoArr = explode(',', $pro->sFileUrl);
            $images = $files = [];
            foreach ($fileInfoArr as $value) {
                if ($value) {
                    $valueArr = explode('.', $value);
                    if (in_array($valueArr[count($valueArr) - 1], ['jpg','jpeg','png','bpm','gif'])) {
                        $images[] = $value;
                    } else {
                        $files[] = $value;
                    }
                }
            }
            $fileInfo['sImages'] = implode(',', $images);
            $fileInfo['sFiles'] = implode(',', $files);
            $fileInfo['ids'] = $idStr;
        }
        $this->view->pick('operatePro/showFileForm');
        Assets::viewer();
        Assets::easyUI('../customer/js/myMain.js');
        Assets::importJs('js/operatePro/showFileForm.js');
        return $this->view->setVars([
            'info' => json_encode($fileInfo)
        ]);
    }

    /**
     * 删除附件
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180910
     */
    public function delFilesAction()
    {
        $postData = $this->request->getPost();
        if (!$postData['id'] || (!$postData['idNum'] && $postData['idNum'] !== '0')
            || !in_array($postData['type'], ['file', 'image'])) {
            return $this->sendErrorResponse(400, '参数错误');
        }
        if (strpos($postData['id'], '+') === false) {//最高层
            $pro = XHBpmOperatePro::findFirst([
                'conditions' => 'bDelete = 0 and iId = :iId:',
                'bind' => ['iId' => $postData['id']]
            ]);
        } else {
            $id = explode('+', $postData['id']);
            $pro = XHBpmOperateProNode::findFirst([
                'conditions' => 'bDelete = 0 and iNodeId = :iNodeId: and iOperateProId = :iOperateProId:',
                'bind' => ['iNodeId' => $id[1], 'iOperateProId' => $id[0]]
            ]);
        }
        if (!$pro) {
            return $this->sendErrorResponse(500, '找不到数据');
        }
        if ($pro->sFileUrl) {
            $fileInfoArr = explode(',', $pro->sFileUrl);
            $images = $files = [];
            foreach ($fileInfoArr as $value) {
                if ($value) {
                    $valueArr = explode('.', $value);
                    if (in_array($valueArr[count($valueArr) - 1], ['jpg','jpeg','png','bpm','gif'])) {
                        $images[] = $value;
                    } else {
                        $files[] = $value;
                    }
                }
            }
            if ($postData['type'] == 'image' && $images && isset($images[$postData['idNum']])) {
                unset($images[$postData['idNum']]);
            } elseif ($postData['type'] == 'file' && $files && isset($files[$postData['idNum']])) {
                unset($files[$postData['idNum']]);
            } else {
                return $this->sendSuccessResponse('成功');
            }
            $pro->sFileUrl = implode(',', array_merge($images, $files));
            if (!$pro->save()) {
                return $this->sendErrorResponse(500, '删除失败');
            }
        }
        return $this->sendSuccessResponse('成功');
    }

    /**
     * 添加运营项目页面
     *
     * @return \Phalcon\Mvc\View|string
     *
     * create by qgz 20180826
     */
    public function addOperateProAction()
    {
        if (!Power::exist('Bpm_OperatePro_Add')) {
            return $this->sendViewError('您没有权限增加');
        }
        $this->view->pick('operatePro/operateProForm');
        Assets::datetimePicker();
        Assets::viewer();
        $this->di->get('assets')
                 ->addCss('assets/fileinput/fileinput.css')
                 ->addJs('customer/js/fileinput.min.js')//修改过的
                 ->addJs('customer/js/zh.js');
        Assets::select2();
        Assets::easyUI('../customer/js/myMain.js');
        Assets::importJs('js/operatePro/operateProForm.js');
        $tempArr = [];
        $data = XHBpmTemplate::find([
            'columns' => 'iTPId, sTPName', 'conditions' => "bDelete = 0 AND sTag = 'itemImpl' "
        ])->toArray();
        if ($data) {
            $tempArr = array_column($data, 'sTPName', 'iTPId');
        }
        $tempArr = ['' => '请选择'] + $tempArr;
        return $this->view->setVars([
            'tempArr' => $tempArr,
        ]);
    }

    /**
     * 获取学校数组
     *
     * @return array|\Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     * @throws \Helpers\XhException
     *
     * create by qgz 20180826
     */
    public function getSchoolListDataAction()
    {
        $return = [];
        $data = School::getPower(true);//加权限
        if (!$data) {
            return $return;
        } elseif ($data === true) {
            $data = XhschoolInfo::getSchoolArray();
        }
        foreach ($data as $key => $value) {
            $return[] = ['id' => $key, 'text' => $value];
        }
        return $this->sendJsonResponse($return);
    }

    /**
     * 上传附件
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180909
     */
    public function updateFileAction()
    {
        if (!$this->request->hasFiles()) {
            return $this->sendErrorResponse(400, '缺少文件');
        }
        $file = $this->request->getUploadedFiles()[0];
        if (!in_array(strtolower($file->getExtension()), [
            'jpg','jpeg','png','bpm','gif','xlsx','docx','doc','pdf','xls'])) {
            return $this->sendErrorResponse(400, '文件类型不正确');
        }
        $filePath = Tool::buildPath(Main::getConfigByName('fileSave')['temp'], $file->getName());
        $fileName = $file->getName();
        $file->moveTo($filePath);
        $url = Main::uploadToFileManageSystem($filePath, 'img', null, true);
        if (!$url) {
            return $this->sendErrorResponse(500, '文件上传失败:没有文件url');
        } else {
            return $this->sendSuccessResponse(['url' => $url, 'fileName' => $fileName]);
        }
    }

    /**
     * 添加运营项目数据
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180826
     */
    public function saveOperateProDataAction()
    {
        $postData = $this->request->getPost();
        if (!$postData['school'] || !$postData['temp'] || !$postData['startTime']) {
            return $this->sendErrorResponse(400, '请填写完整信息');
        }
        $tempData = XHBpmNode::find([
            'conditions' => 'bDelete = 0 AND iTPId = :iTPId:', 'bind' => ['iTPId' => $postData['temp']]
        ]);
        if (!$tempData) {
            return $this->sendErrorResponse(500, '找不到模板数据');
        }
        $this->db->begin();
        $pro = new XHBpmOperatePro();
        $pro->iSchoolId = $postData['school'];
        $pro->iTempId = $postData['temp'];
        $pro->tStartDate = trim($postData['startTime']);
        $pro->sRemark = $postData['remark'];
        if ($postData['teacher']) {
            $pro->sTeaList = implode(',', $postData['teacher']);
        }
        if ($postData['fileUrl']) {
            $pro->sFileUrl = $postData['fileUrl'];
        }
        if (!$pro->save()) {
            $this->db->rollback();
            return $this->sendErrorResponse(500, '保存失败');
        }
        $addDateArr = [];
        foreach ($tempData as $value) {
            $nodePro = new XHBpmOperateProNode();
            $nodePro->iNodeId = $value->iNodeId;
            $nodePro->iTempId = $postData['temp'];
            $nodePro->iParentId = $value->iParentId;
            $nodePro->iOperateProId = $pro->iId;
            $nodePro->iSort = $value->iSort;
            if ($value->iParentId == 0) {
                $nodePro->tStartDate = trim($postData['startTime']);
            }
            if (!$nodePro->save()) {
                $this->db->rollback();
                return $this->sendErrorResponse(500, '保存失败');
            }
            if ($value->iParentId == 0) {//是最上一层，自动算出开始结束时间
                $addDateArr[] = $nodePro->iId;
            }
        }
        if ($addDateArr) {
            $this->addStartAndEndDate($addDateArr, trim($postData['startTime']));
        }
        $this->db->commit();
        return $this->sendSuccessResponse('成功');
    }

    /**
     * 计算开始结束时间
     *
     * @param array $idArr
     * @param string $startDate
     *
     * @return bool
     *
     * create by qgz 201800828
     */
    public function addStartAndEndDate($idArr = [], $startDate = '')
    {
        if (!$idArr || !$startDate) {
            return false;
        }
        $nowDate = $startDate;
        foreach ($idArr as $id) {
            $data = XHBpmOperateProNode::findFirst([
                'conditions' => 'bDelete = 0 and iId = :iId:',
                'bind' => ['iId' => $id]
            ]);
            if ($data) {
                $data->tStartDate = $nowDate;
                $nowDate = date('Y-m-d', strtotime("+1 week", strtotime($nowDate)));
                $data->tEndDate = $nowDate;
                $data->save();
            }
        }
        return true;
    }

    /**
     * 审核完成
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180826
     * modify by qgz 20180918 添加类型，审核完成和取消完成
     */
    public function checkOperateProAction()
    {
        if (!Power::exist('Bpm_OperatePro_Edit')) {
            return $this->sendErrorResponse(400, '您没有权限操作');
        }
        $postData = $this->request->getPost();
        if (!$postData['id']) {
            return $this->sendErrorResponse(400, '缺少id');
        }
        if (!in_array($postData['type'], [1, 2])) {
            return $this->sendErrorResponse(400, '操作类型不正确');
        }
        $setStatus = $postData['type'] == 1 ? 2 : 1;
        $setProgress = $postData['type'] == 1 ? 1 : 0;
        $idArr = [];
        $this->db->begin();
        if (strpos($postData['id'], '_') === false) {//第一层
            $pro = XHBpmOperatePro::findFirst(['conditions' => 'iId = :iId:', 'bind' => ['iId' => $postData['id']]]);
        } else {
            $idArr = explode('_', $postData['id']);//iOperateProId _ iNodeId
            $pro = XHBpmOperateProNode::findFirst([
                'conditions' => 'bDelete = 0 and iOperateProId = :id: and iNodeId = :nodeId:',
                'bind' => ['id' => $idArr[0], 'nodeId' => $idArr[1]]
            ]);
            if (!$pro) {
                $this->db->rollback();
                return $this->sendErrorResponse(500, '未找到数据');
            }
        }
        if (!$pro) {
            $this->db->rollback();
            return $this->sendErrorResponse(500, '未找到数据');
        }
        $pro->iStatus = $setStatus;
        $pro->sProgress = $setProgress;//完成时该节点进度设为100%
        $pro->iCheckUser = User::getId();
        $pro->tCompleteDate = date('Y-m-d H:i:s', time());
        if ($postData['remark']) {
            if ($pro->sRemark) {
                $pro->sRemark .= '；' . $postData['remark'];
            } else {
                $pro->sRemark = $postData['remark'];
            }
        }
        if (!$pro->save()) {
            $this->db->rollback();
            return $this->sendErrorResponse(500, '修改失败');
        }
        if ($postData['resetDepth'] == 'true') {//将子节点状态改为完成或取消完成
            $handle1 = $this->handleNodeComplete($postData['id'], $postData['type']);
            if (!$handle1) {
                $this->db->rollback();
                return $this->sendErrorResponse(500, '更新状态错误');
            }
        }
        if ($idArr) {//非第一层
            $handle2 = $this->handleNodeProgress($idArr[0], $idArr[1], $postData['type']);//计算并更新节点进度
            if (!$handle2) {
                $this->db->rollback();
                return $this->sendErrorResponse(500, '更新进度错误');
            }
        }
        $this->db->commit();
        return $this->sendSuccessResponse('成功');
    }

    /**
     * 计算节点的进度百分比
     *
     * @param string $operateId
     * @param string $nodeId
     * @param int $type
     *
     * @return bool
     *
     * create by qgz 20180918
     */
    public function handleNodeProgress($operateId = '', $nodeId = '', $type = 1)
    {
        $nodesData = XHBpmOperateProNode::find([
            'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId:',
            'bind' => ['iOperateProId' => $operateId]
        ])->toArray();
        $deepNodes = $parentPath = [];
        $parentNodes = array_unique(array_column($nodesData, 'iParentId'));
        if (!$nodesData) {
            return true;
        }
        foreach ($nodesData as $nodeData) {
            if (!in_array($nodeData['iNodeId'], $parentNodes)) {
                $deepNodes[] = $nodeData;//所有最底层叶子节点数据
            }
        }
        if ($deepNodes) {
            $allDeepNodes = $progress = [];
            $deepInfoArr = array_column($deepNodes, null, 'iNodeId');
            foreach ($deepNodes as $value) {
                $parentPath[$value['iNodeId']] = $this->getPass($value['iNodeId'], $nodesData, []);//每个叶子结点的父级节点路径
            }
            foreach ($parentPath as $key => $value) {
                foreach ($value as $item) {
                    $allDeepNodes[$item][] = $key;//有叶子结点的节点下所有的叶子结点
                }
            }
            foreach ($allDeepNodes as $key => $value) {
                $progress[$key] = $this->runProgress($value, $deepInfoArr);//计算百分比
            }
            $this->db->begin();
            if (in_array(0, array_keys($progress))) {//最顶层学校
                $pro = XHBpmOperatePro::findFirst(['conditions' => 'iId = :iId:', 'bind' => ['iId' => $operateId]]);
                $pro->sProgress = $progress[0];
                if (!$pro->save()) {
                    $this->db->rollback();
                    return false;
                }
            }
            $nodesDataArr = XHBpmOperateProNode::find([
                'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId:',
                'bind' => ['iOperateProId' => $operateId]
            ]);
            foreach ($nodesDataArr as $datum) {
                if (in_array($datum->iNodeId, array_keys($progress))) {
                    $setProgress = $type == 1 ? 1 : 0;//当前节点直接设为100%
                    $datum->sProgress = $datum->iNodeId == $nodeId ? $setProgress : $progress[$datum->iNodeId];
                    if (!$datum->save()) {
                        $this->db->rollback();
                        return false;
                    }
                }
            }
            $this->db->commit();
        }
        return true;
    }

    /**
     * 计算叶子结点的父节点的路径
     *
     * @param $id
     * @param $data
     * @param $pass
     *
     * @return array
     *
     * create by qgz 20180903
     */
    public function getPass($id, $data, $pass)
    {
        $nowId = '';
        foreach ($data as $key => $value) {
            if ($value['iNodeId'] == $id) {
                $pass[] = $value['iParentId'];
                $nowId = $value['iParentId'];
                unset($data[$key]);
            }
        }
        if ($nowId != 0) {
            $pass = $this->getPass($nowId, $data, $pass);
        }
        return $pass;
    }

    /**
     * 计算百分比
     *
     * @param $idArr
     * @param $data
     *
     * @return float
     *
     * create by qgz 20180831
     */
    public function runProgress($idArr, $data)
    {
        $total = count($idArr);
        $finish = 0;
        foreach ($idArr as $value) {
            if ($data[$value]['iStatus'] == 2) {
                $finish++;
            }
        }
        return round($finish / $total, 4);
    }

    /**
     * 根据id将其子节点下状态和进度设为完成和100%
     *
     * @param $id
     * @param $type
     *
     * @return bool
     *
     * create by qgz 20180918
     */
    public function handleNodeComplete($id, $type)
    {
        if (strpos($id, '_') === false) {//第一层
            $pro = XHBpmOperateProNode::find([
                'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId:',
                'bind' => ['iOperateProId' => $id]
            ]);
            if ($pro) {
                $setStatus = $type == 1 ? 2 : 1;
                $setProgress = $type == 1 ? 1 : 0;
                foreach ($pro as $value) {
                    $value->iStatus = $setStatus;
                    $value->sProgress = $setProgress;
                    if (!$value->save()) {
                        return false;
                    }
                }
            }
        } else {
            $idArr = explode('_', $id);//iOperateProId _ iNodeId
            $pro = XHBpmOperateProNode::findFirst([
                'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId: and iNodeId = :iNodeId:',
                'bind' => ['iOperateProId' => $idArr[0], 'iNodeId' => $idArr[1]]
            ]);
            if ($pro) {
                $handleStatus = $this->handleFinishStatus([$idArr[1]], $idArr[0], $type);
                if (!$handleStatus) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 递归设置子节点状态为完成，进度为100%
     *
     * @param $nodeIdArr
     * @param $operateId
     * @param $type
     *
     * @return bool
     *
     * create by qgz 20180918
     */
    public function handleFinishStatus($nodeIdArr, $operateId, $type)
    {
        if (!$nodeIdArr) {
            return true;//最底层终止递归
        }
        $pro = XHBpmOperateProNode::find([
                'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId: and iParentId in ({iParentId:array})',
            'bind' => ['iOperateProId' => $operateId, 'iParentId' => $nodeIdArr]
        ]);
        if (!$pro) {//最底层终止递归
            return true;
        }
        $nextNodeIdArr = [];
        $setStatus = $type == 1 ? 2 : 1;
        $setProgress = $type == 1 ? 1 : 0;
        foreach ($pro as $value) {
            $value->iStatus = $setStatus;
            $value->sProgress = $setProgress;
            if (!$value->save()) {
                return false;
            }
            $nextNodeIdArr[] = $value->iNodeId;
        }
        if ($nextNodeIdArr) {
            $handleStatus = $this->handleFinishStatus($nextNodeIdArr, $operateId, $type);
            if (!$handleStatus) {
                return false;
            }
        } else {
            return true;
        }
        return true;
    }

    /**
     * 删除
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180826
     */
    public function delOperateProAction()
    {
        if (!Power::exist('Bpm_OperatePro_Del')) {
            return $this->sendErrorResponse(400, '您没有权限删除');
        }
        $postData = $this->request->getPost();
        if (!$postData['id']) {
            return $this->sendErrorResponse(400, '缺少id');
        }
        if (strpos($postData['id'], '_') !== false) {
            return $this->sendErrorResponse(400, '节点不可删除');
        }
        $this->db->begin();
        $pro = XHBpmOperatePro::findFirst([
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $postData['id']]]);
        if (!$pro) {
            return $this->sendErrorResponse(500, '未找到数据');
        }
        $pro->bDelete = 1;
        if (!$pro->save()) {
            $this->db->rollback();
            return $this->sendErrorResponse(500, '修改失败');
        }
        $nodePro = XHBpmOperateProNode::find([
            'conditions' => 'bDelete = 0 and iOperateProId = :id:',
            'bind' => ['id' => $postData['id']]
        ]);
        if ($nodePro) {
            foreach ($nodePro as $item) {
                $item->bDelete = 1;
                if (!$item->save()) {
                    $this->db->rollback();
                    return $this->sendErrorResponse(500, '修改节点表失败');
                }
            }
        }
        $this->db->commit();
        return $this->sendSuccessResponse('成功');
    }

    /**
     * 编辑页面
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface|\Phalcon\Mvc\View
     *
     * create by qgz 20180828
     */
    public function modifyOperateProAction()
    {
        if (!Power::exist('Bpm_OperatePro_Edit')) {
            return $this->sendViewError('您没有权限修改');
        }
        $id = $this->request->getQuery('id');
        $depth = $this->request->getQuery('depth');
        if (!$id || ($depth === null || $depth === '')) {
            return $this->sendErrorResponse(400, '缺少参数');
        }
        $this->view->pick('operatePro/modifyOPForm');
        Assets::datetimePicker();
        Assets::viewer();
        $this->di->get('assets')
                 ->addCss('assets/fileinput/fileinput.css')
                 ->addJs('customer/js/fileinput.min.js')//修改过的
                 ->addJs('customer/js/zh.js');
        Assets::select2();
        Assets::easyUI();
        Assets::easyUI('../customer/js/myMain.js');
        Assets::importJs('js/operatePro/modifyOPForm.js');
        $params = [];
        if ($depth == 0) {//第一层
            $type = 1;
            $pro = XHBpmOperatePro::findFirst([
                'conditions' => 'bDelete = 0 and iId = :iId:',
                'bind' => ['iId' => $id]
            ]);
            if (!$pro) {
                return $this->sendErrorResponse(500, '未找到数据');
            }
            $params['startDate'] = $pro->tStartDate;
            $params['endDate'] = $pro->tEndDate;
            $params['teaList'] = $pro->sTeaList;
            $params['school'] = $pro->iSchoolId;
            $params['iId'] = $pro->iId;
            $remark = $pro->sRemark;
            $progress = $pro->sProgress;
        } else {//非第一层
            $type = 2;
            if (strpos($id, '_') !== false) {
                $idArr = explode('_', $id);
                $pro = XHBpmOperateProNode::findFirst([
                    'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId: and iNodeId = :iNodeId:',
                    'bind' => ['iOperateProId' => $idArr[0],'iNodeId' => $idArr[1]]
                ]);
                if (!$pro) {
                    return $this->sendErrorResponse(500, '未找到数据');
                }
                $params['startDate'] = $pro->tStartDate;
                $params['endDate'] = $pro->tEndDate;
                $params['iId'] = $pro->iOperateProId . '_' . $pro->iNodeId;
                $remark = $pro->sRemark;
                $progress = $pro->sProgress;
            } else {
                return $this->sendErrorResponse(400, 'id格式不正确');
            }
        }
        $params['type'] = $type;
        $params['depth'] = $depth;
        $params['remark'] = $remark;
        $params['progress'] = ceil($progress * 100);
        return $this->view->setVars($params);
    }

    /**
     * 获取关联教师
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180828
     */
    public function getConnTeaDataAction()
    {
        $postData = $this->request->getPost();
        if (!$postData['id'] || !$postData['school']) {
            return $this->sendErrorResponse(400, '参数错误');
        }
        $return = ['allTeaList' => [], 'teaList' => []];
        $allTeaData = XhsysUser::find([
            'columns' => 'iUserId, sUserName',
            'conditions' => 'bDelete = 0 AND bDisable = 0 AND 
            bHistory = 0 AND iUserType = 4 AND iSchoolId = :iSchoolId:',
            'bind' => ['iSchoolId' => $postData['school']]
        ]);
        if ($allTeaData) {
            $allTeaData = $allTeaData->toArray();
            foreach ($allTeaData as $value) {
                $return['allTeaList'][] = ['id' => $value['iUserId'], 'text' => $value['sUserName']];
            }
        }
        $pro = XHBpmOperatePro::findFirst([
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $postData['id']]
        ]);
        if (!$pro) {
            return $this->sendErrorResponse(500, '未找到数据');
        }
        $return['teaList'] = $pro->sTeaList ? explode(',', $pro->sTeaList) : [];
        return $this->sendJsonResponse($return);
    }

    /**
     * 根据学校id获取教师数据
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180828
     */
    public function getTeaDataBySchoolAction()
    {
        $schoolId = $this->request->getPost('schoolId');
        $return = [];
        if ($schoolId) {
            $allTeaData = XhsysUser::find([
                'columns' => 'iUserId, sUserName',
                'conditions' => 'bDelete = 0 AND bDisable = 0 AND bHistory = 0 
                AND iUserType = 4 AND iSchoolId = :iSchoolId:',
                'bind' => ['iSchoolId' => $schoolId]
            ]);
            if ($allTeaData) {
                $allTeaData = $allTeaData->toArray();
                foreach ($allTeaData as $value) {
                    $return[] = ['id' => $value['iUserId'], 'text' => $value['sUserName']];
                }
            }
        }
        return $this->sendJsonResponse($return);
    }

    /**
     * 修改信息
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20180828
     */
    public function modifyOperateProDataAction()
    {
        $postData = $this->request->getPost();
        if (!$postData['id']) {
            return $this->sendErrorResponse(400, '缺少id');
        }
        if ($postData['type'] == 1) {
            $pro = XHBpmOperatePro::findFirst([
                'conditions' => 'bDelete = 0 and iId = :iId:',
                'bind' => ['iId' => $postData['id']]
            ]);
            if (!$pro) {
                return $this->sendErrorResponse(500, '未找到数据');
            }
            if ((is_array($postData['teaList']) && empty($postData['teaList'][0])) || !$postData['teaList'][0]) {
                $teaList = '';
            } else {
                $teaList = implode(',', $postData['teaList']);
            }
            $pro->sTeaList = $teaList;
        } else {
            if (strpos($postData['id'], '_') !== false) {
                $idArr = explode('_', $postData['id']);
                $pro = XHBpmOperateProNode::findFirst([
                    'conditions' => 'bDelete = 0 and iOperateProId = :iOperateProId: and iNodeId = :iNodeId:',
                    'bind' => ['iOperateProId' => $idArr[0],'iNodeId' => $idArr[1]]
                ]);
                if (!$pro) {
                    return $this->sendErrorResponse(500, '未找到数据');
                }
            } else {
                return $this->sendErrorResponse(400, 'id格式不正确');
            }
        }
        $pro->sProgress = $postData['sProcess'] / 100;
        $pro->tStartDate = trim($postData['startTime']);
        $pro->tEndDate = trim($postData['endTime']);
        $pro->sRemark = $postData['remark'];
        if ($postData['fileUrl']) {
            $pro->sFileUrl .= substr($pro->sFileUrl, -1) == ',' ?
                $postData['fileUrl'] : ',' . $postData['fileUrl'];
        }
        if (!$pro->save()) {
            return $this->sendErrorResponse(500, '保存失败');
        }
        return $this->sendSuccessResponse('成功');
    }

    /**
     * 数据统计table页
     *
     * @return \Phalcon\Mvc\View
     *
     * create by qgz 20181129
     */
    public function showDataStatTableAction()
    {
        $id = $this->request->getQuery('id');
        $startDate = $this->request->getQuery('startDate');
        $endDate = $this->request->getQuery('endDate');
        Assets::easyUI('js/operatePro/showDataStatTable.js');
        $this->view->pick('operatePro/showDataStatTable');
        return $this->view->setVars(['id' => $id, 'startDate' => $startDate, 'endDate' => $endDate]);
    }

    /**
     * 应用数据统计 copy from school_week/appCountAction
     *
     * @return \Phalcon\Mvc\View
     * @throws \Helpers\XhException
     *
     * create by qgz 20180828
     */
    public function statAppDataAction()
    {
        if (!Power::exist('Bpm_OperatePro_Stat')) {
            return $this->sendViewError('您没有权限查看');
        }
        $postData = $this->request->getQuery();
        if (strpos($postData['iId'], '_') !== false) {
            $id = explode('_', $postData['iId']);
            $id = $id[0];
        } else {
            $id = $postData['iId'];
        }
        $schoolId = XHBpmOperatePro::findFirst([
            'columns' => 'iSchoolId',
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $id]
        ]);
        if (!$schoolId) {
            return $this->sendViewError('找不到学校数据');
        }
        $this->view->pick('operatePro/appCount');
        Assets::importJs('../frontend/js/school_week/appCount.js');
        Assets::select2();
        Assets::sweetAlert2();
        $schoolData = XhschoolInfo::getSchoolArray();
        return $this->view->setVars([
            'schoolName' => $schoolData[$schoolId->iSchoolId],
            'school' => (int)$schoolId->iSchoolId,
            'startDate' => $postData['startDate'] ? date('Y-m-d', strtotime($postData['startDate'])) : null,
            'endDate' => $postData['endDate'] ? date('Y-m-d', strtotime($postData['endDate'])) : null,
            'viewAll'   => School::getPower() === true,
            'schoolArr' => User::getSchool(true),
        ]);
    }

    /**
     * 教师应用页
     *
     * @return \Phalcon\Mvc\View|string
     *
     * create by qgz 20181129
     */
    public function statTeaAppDataAction()
    {
        $getData = $this->request->getQuery();
        $this->view->pick('operatePro/teaAppCount');
        Assets::easyUI('js/operatePro/teaAppCount.js');
        if (strpos($getData['iId'], '_') !== false) {
            $id = explode('_', $getData['iId']);
            $id = $id[0];
        } else {
            $id = $getData['iId'];
        }
        $startDate = trim($getData['startDate']);
        $endDate = trim($getData['endDate']);
        $school = XHBpmOperatePro::findFirst([
            'columns' => 'iSchoolId, sTeaList',
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $id]
        ]);
        if (!$school->iSchoolId) {
            return $this->sendViewError('找不到学校数据');
        }
        $schoolData = XhschoolInfo::getSchoolArray();
        return $this->view->setVars([
            'iId' => $getData['iId'],
            'schoolName' => $schoolData[$school->iSchoolId],
            'startDate' => $startDate,
            'endDate' => $endDate,
        ]);
    }

    /**
     * 获取统计老师应用数据
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20181205
     */
    public function getStatTeaAppAction()
    {
        $getData = $this->request->getPost();
        if (strpos($getData['iId'], '_') !== false) {
            $id = explode('_', $getData['iId']);
            $id = $id[0];
        } else {
            $id = $getData['iId'];
        }
        $startDate = trim($getData['startDate']);
        $endDate = trim($getData['endDate']);
        $school = XHBpmOperatePro::findFirst([
            'columns' => 'iSchoolId, sTeaList',
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $id]
        ]);
        if (!$school->iSchoolId) {
            return $this->sendErrorResponse(400, '找不到学校数据');
        }
        if (!(trim($school->sTeaList) && $startDate && $endDate)) {
            return $this->sendJsonResponse([]);
        }
        try {
            $startDate = strtotime($startDate . ' 00:00:00');
            $endDate = strtotime($endDate . ' 23:59:59');
            $data = BigData::getTeaAppStatData($school->iSchoolId, trim($school->sTeaList), $startDate, $endDate);
            if (!$data) {
                return $this->sendJsonResponse([]);
            }
            $data = $this->handleTeaAppData($data);
            return $this->sendJsonResponse($data);
        } catch (\Exception $e) {
            return $this->sendErrorResponse(500, '获取接口数据失败', $e->getMessage());
        }
    }


    /**
     * 处理成表格展示的数据
     *
     * @param array $data
     *
     * @return array
     *
     * create by qgz 20181206
     */
    public function handleTeaAppData($data = [])
    {
        if (!$data) {
            return [];
        }
        $appArr = ['cloudWork' => '云作业', 'exerciseKing' => '学海题舟', 'langBasic' => '语文基础',
                   'oralTrain' => '口语训练', 'smartClass' => '智通课堂'];
        $typeArr = ['correctRate' => '批改率', 'fixNum' => '布置次数', 'practiceNum' => '自练题量',
                    'recorrectRate' => '二次批改率', 'uploadRate' => '上交率'];
        //返回数据的老师id数组
        $idNameArr = $dataArr = $returnArr = $return = $rowHeight = [];
        foreach ($data as $app => $value) {
            foreach ($value as $item) {
                foreach ($item as $key => $realData) {
                    if ($key != 'tchId' && $key != 'tchName') {//去掉教师id和教师名字段
                        $dataArr[$item['tchId']][$app][] = [$key => $realData];
                        @$rowHeight[$item['tchId']]['row']++;//计算教师行高
                        @$rowHeight[$item['tchId']]['app'][$app]++;//计算应用行高
                    }
                }
                $idNameArr[$item['tchId']] = $item['tchName'];//老师id和名字对
            }
        }
        foreach ($dataArr as $teaId => $value) {
            $isTeaFirstRow = true;
            foreach ($value as $app => $item) {
                foreach ($item as $key => $finaData) {
                    foreach ($finaData as $type => $num) {
                        $returnArr['type'] = isset($typeArr[$type]) ? $typeArr[$type] : '[未知]';
                        if (isset($typeArr[$type]) && in_array($type, ['correctRate', 'recorrectRate', 'uploadRate'])) {
                            $num = $num * 100 . '%';
                        }
                        $returnArr['finish'] = $num;
                    }
                    $returnArr['teaName'] = isset($idNameArr[$teaId]) ? $idNameArr[$teaId] : '[未知]';
                    $returnArr['appName'] = isset($appArr[$app]) ? $appArr[$app] : '[未知]';
                    $returnArr['isTeaFirstRow'] = $isTeaFirstRow;//老师是否第一行
                    $returnArr['isAppFirstRow'] = $key == 0 ? true : false;//应用是否第一行
                    $returnArr['teaRowSpan'] = $isTeaFirstRow ? $rowHeight[$teaId]['row'] : 0;//老师列高度
                    $returnArr['appRowSpan'] = $key == 0 ? $rowHeight[$teaId]['app'][$app] : 0;//应用列高度
                    $isTeaFirstRow = $isAppFirstRow = false;
                    $return[] = $returnArr;
                }
            }
        }
        return $return;
    }

    /**
     * 根据运营项目id获取学校名
     *
     * @return \Phalcon\Http\Response|\Phalcon\Http\ResponseInterface
     *
     * create by qgz 20181207
     */
    public function getSchoolNameAction()
    {
        $getData = $this->request->getPost();
        if (strpos($getData['iId'], '_') !== false) {
            $id = explode('_', $getData['iId']);
            $id = $id[0];
        } else {
            $id = $getData['iId'];
        }
        if (!$id) {
            return $this->sendErrorResponse(400, '数据参数错误');
        }
        $school = XHBpmOperatePro::findFirst([
            'columns' => 'iSchoolId, sTeaList',
            'conditions' => 'bDelete = 0 and iId = :iId:',
            'bind' => ['iId' => $id]
        ]);
        if (!$school->iSchoolId) {
            return $this->sendErrorResponse(400, '找不到学校数据');
        }
        $schoolData = XhschoolInfo::getSchoolArray();
        return $this->sendJsonResponse(['schoolName' => $schoolData[$school->iSchoolId]]);
    }
}
